11.2 FreeRTOS Middleware Support
The FreeRTOS development suite consists of FreeRTOS as the core kernel, with extended functionalities provided by various components such as FreeRTOS+FAT, FreeRTOS+TCP, and third-party middleware stacks for USB and graphics.
11.2.1 FreeRTOS
FreeRTOS is a real-time kernel (or real-time scheduler) on top of which embedded applications can be built to meet their hard real-time requirements. It allows applications to be organized as a collection of independent threads of execution.
FreeRTOS has the following standard features:
-
Pre-emptive or co-operative operation
-
Very flexible task priority assignment
-
Flexible, fast, and lightweight task notification mechanism
-
Queues
-
Binary semaphores
-
Counting semaphores
-
Mutexes
-
Recursive mutexes
-
Software timers
-
Event groups
-
Tick hook functions
-
Idle hook functions
-
Stack overflow checking
-
Trace recording
-
Task run-time statistics gathering
-
Optional commercial licensing and support
-
Full interrupt nesting model (for some architectures)
-
A tick-less capability for extremely low power applications
-
Software managed interrupt stack when appropriate (this can help save RAM)
FreeRTOS is supplied as a set of C source files. Some of the source files are common to all ports, while others are specific to a port.
11.2.1.1 FreeRTOSConfig.h
FreeRTOS is configured by a header file called FreeRTOSConfig.h.
FreeRTOSConfig.h is used to tailor FreeRTOS for use in a specific application.
11.2.1.2 FreeRTOS Common Source Files
Figure 11-1 shows the list of FreeRTOS port source files.
Figure 11-1 FreeRTOS Common Source Files
The following is a brief description of the FreeRTOS port source files:
-
task.c: Provides task-related services
-
list.c: Provides list implementation used by the scheduler
-
queue.c: Provides both queue and semaphore services
-
timers.c: Provides software timer functionality
-
event_groups.c: Provides event group functionality
-
croutine.c: Implements the FreeRTOS co-routine functionality (rarely used now)
11.2.1.3 FreeRTOS Port Specific Source Files
Source files specific to a FreeRTOS port are contained within the portable directory. The portable directory is arranged as a hierarchy, first by compiler, then by processor architecture.
FreeRTOS also considers heap memory allocation to be part of the portable layer. FreeRTOS provides five example heap allocation schemes. The five schemes are named heap_1 to heap_5 and are implemented by the source files heap_1.c to heap_5.c respectively.
11.2.2 FreeRTOS+TCP
FreeRTOS+ TCP is an embedded TCP/IP networking stack that has been designed to work seamlessly on top of the FreeRTOS kernel. For application programs, FreeRTOS+TCP provides an API that is very similar to the popular Berkeley sockets API. This makes it easy to port applications that use the regular sockets API to the FreeRTOS+TCP environment.
Further information on FreeRTOS+TCP is available on FreeRTOS+TCP.
11.2.2.1 Architecture
Figure 11-2 shows different components of a FreeRTOS+TCP network application in the Alif Semiconductor RTSS SDK.
Note that the Alif Semiconductor Network Interface driver depends on the generic Ethernet PHY handling code provided by FreeRTOS+TCP to manage the Ethernet PHY hardware.
11.2.2.2 Network Interface Layer
The Network Interface driver layer provides an interface between the FreeRTOS+TCP networking stack and the networking hardware. This layer implements the functions invoked by the stack to initialize and operate the Ethernet MAC hardware. This layer is responsible for programming the MAC hardware to send out the network packets generated by the networking stack and for routing the incoming Ethernet frames to the stack. The FreeRTOS+TCP stack provides different buffer allocation strategies (see Section 11.2.2.3 Network Buffer Allocation/Management). If the BufferAllocation_1 strategy is used, the Network Interface driver layer is also responsible for statically allocating the memory needed to store network buffers.
The Alif Semiconductor Network Interface driver supports zero-copy transmission and reception, meaning that the network buffers are not copied to local buffers within the driver before being processed by the MAC DMA engine. This avoidance of data copy saves CPU cycles and thus increases performance.
The network buffers hold the packets that are received and are being sent out by the networking stack. The total number of buffers (and their descriptors) is configured by the application using a configuration file (see Section 11.2.2.4 Setting Up and Configuring a FreeRTOS+TCP Application) that is used by the stack. Additionally, the FreeRTOS+TCP stack provides two buffer allocation mechanisms to choose from. This gives the application developer more control over how the buffers are allocated.
If BufferAllocation_1 strategy is chosen, the memory area for the network buffers is statically allocated by the Ethernet Network Interface driver. On the other hand, if BufferAllocation_2 strategy is selected, the network buffers are allocated dynamically from the FreeRTOS heap area. Each scheme has its advantages and disadvantages. More information on buffer allocation strategies can be found on TCP/IP Stack Network Buffers Allocation Schemes.
FreeRTOS+TCP network applications are configured using a configuration header file named FreeRTOSIPConfig.h. This is similar to how a usual FreeRTOS application is configured using FreeRTOSConfig.h file. Various parameters defined in this file can be used to control the execution behavior of both the FreeRTOS+TCP stack and the Network Interface driver. A complete list and description of various parameters can be found on FreeRTOS+TCP Configuration.
More information on FreeRTOS+TCP can be found on FreeRTOS+TCP.
11.2.3 FreeRTOS+FAT
FreeRTOS+FAT is an open-source, fully thread-aware, and scalable FAT12/FAT16/FAT32 DOS/Windows compatible embedded FAT file system.
It provides optional long filename support, optional directory name hashing for speed, task-specific working directories and errno support, and comprehensive error reporting.
Table 11-1 shows the list of filesystem APIs provided by FreeRTOS+FAT.
Table 11-1 FreeRTOS+FAT API Filesystems
Source code organization for FreeRTOS+FAT is shown in Figure 11-3.
Figure 11-3 FreeRTOS+FAT Code Organization
11.2.3.1 FreeRTOS+FAT Configuration
Applications using FreeRTOS+FAT must provide a FreeRTOSFATConfig.h header file that describes the parameters to configure the FreeRTOS+FAT.
11.2.4 Graphics Middleware Support
Various third-party graphics libraries can be utilized along with FreeRTOS to provide graphics support.
11.2.5 USB Middleware Support
Various third-party USB libraries can be utilized along with FreeRTOS to provide USB stack support. Alif intends to use TinyUSB as a solution for the FreeRTOS USB stack.
11.2.5.1 TinyUSB
TinyUSB is an open-source cross-platform USB Host and Device stack for embedded systems.
Figure 11-4 TinyUSB Block Diagram
11.2.5.2 Application
TinyUSB initialization routines are part of the TinyUSB stack. TinyUSB specific callback routines are called through the applications responsible for stack and controller Initializations. The application utilizes a device framework and passes it on to the TinyUSB stack. The device framework is divided into three categories:
-
Descriptors: Device, Configuration, Interface, and Endpoint descriptors. These descriptors hold device-specific information, such as class, configurations, interface, and endpoints supported by the device.
-
String: String descriptor. This descriptor holds the manufacturer, product, and serial number of the USB device.
-
Language: Language descriptor holds the language supported by the device.
11.2.5.3 TinyUSB Stack
TinyUSB stack is responsible for USB Host and Device class implementation, memory resourcing, callbacks, stack initialization, initialization of synchronization resources, data transfer routines, buffer management, and queue management. The layer interacts with the Application and with the hardware (MCU) through the OS Abstraction Layer (OSAL).
The requests made by USB Host, such as GET_DESCRIPTOR, GET_CONFIGURATION, SET_CONFIGURATION, SET_ADDRESS for Device are queued in the TinyUSB stack and made available to the Controller once there is an interrupt for device SETUP. The data to USB Host is made available by TinyUSB stack through data transfer callbacks and other routines.
OS Abstraction Layer: TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR) events into a central queue, then processing them later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources, such as CDC FIFO. Therefore the stack needs to use some of the OS's basic APIs. The device SETUP-related requests are queued by OSAL and on-demand, data is passed by controller through the respective FIFOs. The OSAL is also responsible for providing basic data structures for TinyUSB, which may support concurrency when used with an RTOS. Without an RTOS, it simply handles concurrency issues between the main codes and interrupts.
Dual Role Controller Driver: Driver handles access to hardware registers, endpoint configurations, interrupt handling, DMA transfer, and FIFO maintenance. SETUP/Data requests by USB Host to slave device are handled by the controller. Depending on the type of interrupt (that is, the type of requests made by USB Host) driver makes decisions and interacts with the framework. The return framework calls routines added to the OSAL queue and returns data to the Host through DMA transactions. A few of the events handled by the controller are XferComplete, XferDataStage, XferInProgress, and XferStatsStage.
11.2.5.4 TinyUSB Support for Alif Semiconductor Ensemble DevKit/AppKit
Figure 11-5 shows a simplified diagram of the USBX.
Figure 11-5 Simplified Diagram of TinyUSB
Alif Semiconductor
-
CDC-ACM device class support that handles class requests on interface 0 using a Control/Interrupt endpoint and CDC-ACM data requests on interface 1 using a bulk endpoint.
-
CDC-ACM class initialization, memory resourcing, device framework parsing, and provisioning of data buffers to the driver.
-
TRB creation, DMA transaction initiation, Device, and Endpoint interrupt handling.
11.2.5.5 TinyUSB Working in Device/Host Mode
In Device mode, stack initialization routines are called from the application, followed by device controller initialization routines. The device controller is ready to accept interrupts (Setup from the Host) after configuring the endpoints and device-specific registers. The controller driver gets requests from the Host, calls the queued callbacks in OSAL, and returns data to the Host on specific endpoints through DMA. In Host mode, Setup packets are created by the Host and sent on Endpoint 0 OUT/IN once the device controller is configured and ready to accept Setup packets. The Host continues with additional requests and enumerates the device if all information is passed correctly.
11.2.5.6 TinyUSB Device Stack
TinyUSB Device stack supports multiple device configurations by dynamically changing USB descriptors and different low power functions, such as suspend, resume, and remote wakeup. Following device classes are supported:
-
USB Audio Class 2.0 (UAC2)
-
Bluetooth Host Controller Interface (BTH HCI)
-
Communication Device Class (CDC)
-
Device Firmware Update (DFU): only Runtime
-
Human Interface Device (HID): Generic (In and Out), Keyboard, Mouse, Gamepad
-
Mass Storage Class (MSC): with multiple LUNs
-
Musical Instrument Digital Interface (MIDI)
-
Network with RNDIS, CDC-ECM (work in progress)
-
USB Test and Measurement Class (USBTMC)
-
Vendor-specific class support with generic In and Out endpoints. Can be used with MS OS 2.0 compatible descriptor to load winUSB driver without INF file.
-
WebUSB with vendor-specific class
TinyUSB Host Stack Supports:
-
Human Interface Device (HID): Keyboard, Mouse, Generic
-
Mass Storage Class (MSC)
-
Hub currently only supports 1 level of hub
Figure 11-6 TinyUSB Device Stack